package com.csx.governance.traffic.core.interceptor.outbound;

import com.csx.governance.traffic.core.constants.TrafficAttributeConstants;
import com.csx.governance.traffic.core.context.TrafficRequest;
import com.csx.governance.traffic.core.context.TrafficResponse;
import feign.Request;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.loadbalancer.RequestDataContext;
import org.springframework.core.Ordered;
import org.springframework.http.HttpRequest;

import java.net.URI;

/**
 * <p>请求属性统一初始化器,将某些必要的属性初始化到 出站Request对象中的 Attributes中。</p>
 * <p>注意: 除了此拦截器会对 出站Request对象的Attributes修改外,
 * 还有 {@link TransportAttributesTakeOutboundHandlerInterceptor} 也会修改出站Request对象的Attributes</p>
 * @author cuisongxu
 * @date 2023/4/2 14:16
 */
public class RequestAttributesInitializerOutboundHandlerInterceptor extends TrafficAbstractOutboundHandlerInterceptor{

    private static final Logger logger = LoggerFactory.getLogger(RequestAttributesInitializerOutboundHandlerInterceptor.class);

    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE - 1001;
    }

    @SuppressWarnings("unchecked")
    @Override
    public boolean preHandle(TrafficRequest request, TrafficResponse response) {

        // 处理基于RestTemplate的外调
        if(request.getOriginRequest() instanceof HttpRequest) {
            HttpRequest originRequest = (HttpRequest) request.getOriginRequest();
            String serviceName = originRequest.getURI().getHost();
            request.setAttribute(TrafficAttributeConstants.SERVICE_NAME, serviceName);

        // 处理基于OpenFeign的外调
        }else if(request.getOriginRequest() instanceof Request) {
            Request originRequest = (Request) request.getOriginRequest();
            String serviceName = URI.create(originRequest.url()).getHost();
            request.setAttribute(TrafficAttributeConstants.SERVICE_NAME, serviceName);
        } else if(request.getOriginRequest() instanceof org.springframework.cloud.client.loadbalancer.Request) {
            org.springframework.cloud.client.loadbalancer.Request<RequestDataContext> originRequest = (org.springframework.cloud.client.loadbalancer.Request<RequestDataContext>) request.getOriginRequest();
            String serviceName = originRequest.getContext().getClientRequest().getUrl().getHost();
            request.setAttribute(TrafficAttributeConstants.SERVICE_NAME, serviceName);
        } else {
            logger.error("unsupported outbound request type: {}", request.getOriginRequest());
            throw new RuntimeException("unsupported outbound request type: " + request.getOriginRequest());
        }
        return super.preHandle(request, response);
    }
}
